package com.spc.car.service.file.impl;

import com.spc.car.common.exception.CustomException;
import com.spc.car.common.utils.StringUtils;
import com.spc.car.common.utils.file.FileUploadUtils;
import com.spc.car.common.utils.file.FileUtils;
import com.spc.car.data.entity.sys.SysAttachment;
import com.spc.car.data.entity.sys.SysUser;
import com.spc.car.data.service.sys.SysAttachmentService;
import com.spc.car.service.file.FileService;
import org.apache.commons.collections.MapUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

@Service
public class FileServiceImpl implements FileService {

    @Autowired
    private SysAttachmentService attachmentService;

    public SysAttachment toSysAttachment(Map<String, Object> params, SysUser sysUser) {
        SysAttachment sysAttachment = new SysAttachment();
        if (MapUtils.isNotEmpty(params)) {
            try {
                sysAttachment = mapToBean(params, SysAttachment.class);
            } catch (Exception e) {
                e.printStackTrace();
            }
            if (StringUtils.isNotBlank(sysAttachment.getProjectCode())) {
                sysAttachment.setFileType("P");
            } else if (null != sysAttachment.getDeptId()) {
                sysAttachment.setFileType("D");
            } else if (StringUtils.isNotBlank(sysAttachment.getOrgCode())) {
                sysAttachment.setFileType("O");
            } else if (Objects.nonNull(sysAttachment.getPersonId())) {
                sysAttachment.setFileType("E");
            }
        }

        if (StringUtils.isBlank(sysAttachment.getFileType())) {
            sysAttachment.setFileType("U");
        }
        sysAttachment.setFileOwner(sysUser.getUserName());
        sysAttachment.setFileCode(String.format("%09d", sysUser.getUserId()) + "" + System.nanoTime());
        sysAttachment.setFileUrl(toRelativeFilePath(sysAttachment,
                null == params.get("customPath") ? "":params.get("customPath").toString(),
                sysUser.getUserId()));

        return sysAttachment;
    }

    public String toRelativeFilePath(SysAttachment sysAttachment, String customPath, Long userId) {
        Map<String, String> fileTypeMapping = new HashMap<>();
        fileTypeMapping.put("D", "/department/" + sysAttachment.getDeptId());
        fileTypeMapping.put("P", "/project/" + sysAttachment.getProjectCode());
        fileTypeMapping.put("U", "/user/" + sysAttachment.getFileOwner());
        fileTypeMapping.put("O", "/org/" + sysAttachment.getOrgCode());
        fileTypeMapping.put("E", "/person/" + sysAttachment.getPersonId());

        String extendPath = StringUtils.defaultIfBlank(customPath, "");
        if (StringUtils.isNotBlank(extendPath)) {
            if (!extendPath.startsWith("/")) {
                extendPath = "/" + extendPath;
            }
            if (!extendPath.endsWith("/")) {
                extendPath = extendPath + "/";
            }
        }
        String path = fileTypeMapping.get(sysAttachment.getFileType())
                +  extendPath;
        if (!path.endsWith("/")) {
            path = path + "/";
        }
        path = path + sysAttachment.getFileCode();

        return path;
    }

    @Transactional
    public SysAttachment upload(MultipartFile multipartFile, String baseDir,
                       Map<String, Object> params, SysUser sysUser) {
        SysAttachment sysAttachment = toSysAttachment(params, sysUser);
        String fileName = multipartFile.getOriginalFilename();
        sysAttachment.setFileSize(multipartFile.getSize() / 1024);
        sysAttachment.setFileSuffix(fileName.substring(fileName.lastIndexOf(".")));
        sysAttachment.setFileName(FileUtils.getFileNameNoEx(fileName));
        sysAttachment.setFileUrl(baseDir + sysAttachment.getFileUrl() + sysAttachment.getFileSuffix());
        attachmentService.save(sysAttachment);

        try {
            FileUploadUtils.save(sysAttachment.getFileUrl(), multipartFile);
        } catch (Exception e) {
            e.printStackTrace();
            throw new CustomException("上传文件失败");
        }
        return sysAttachment;
    }

    public <T> T mapToBean(Map<String, Object> map, Class<T> cls) throws Exception {
        T object = cls.newInstance();
        for (String key : map.keySet()){
            Field field = cls.getDeclaredField(key);
            field.setAccessible(true);
            if (field.getType().equals(Long.class)) {
                field.set(object, Long.parseLong(map.get(key).toString()));
            } else {
                field.set(object, map.get(key));
            }

        }
        return object;
    }
}
